/*
 *  Copyright (C) 1993  Robert Davis
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of Version 2, or any later version, of 
 *  the GNU General Public License as published by the Free Software 
 *  Foundation.
 */

static char RCSId[]="$Id: ThreeDPane.m,v 1.8 1993/05/18 03:55:44 davis Exp $";


#import <appkit/Application.h>
#import <appkit/Box.h>
#import <appkit/Matrix.h>
#import <appkit/Slider.h>
#import <appkit/TextField.h>
#import <appkit/TextFieldCell.h>
#import <appkit/View.h>

#import "ContourOptionsPanel.h"
#import "GnuplotPlot.h"
#import "Status.h"
#import "StatusContour.h"
#import "ThreeDPane.h"


#define	SURF_WIREFRAME	0
#define	SURF_OPAQUE	1
#define	SURF_INVISIBLE	2


@interface ThreeDPane (Private)

- _updateRotationIsThreeD:(BOOL)isThreeD;
- _updateContourIsThreeD:(BOOL)isThreeD;
- _updateSurfaceTypeIsThreeD:(BOOL)isThreeD;
- _updateIsoSamplesIsThreeD:(BOOL)isThreeD;

@end




@implementation ThreeDPane


- init
{
    [super init];

    [NXApp loadNibSection: "ThreeDPane.nib"
		    owner: self
		withNames: NO
		 fromZone: [self zone]];

    icon = "InspectorThreeD.tiff";

    return self;
}


- free
{
    if (contourOptionsPanel)
	[contourOptionsPanel free];

    return [super free];
}


/*  
 *  Overridden from Pane.
 */
- selectControl:sender
{
    [isoSamplesMatrix selectText:self];
    return self;
}


- (BOOL)updateStatus:aStatus doc:aDoc
{
    id oldStatus = status;
    id oldDoc = doc;

    /*  
     *  We only bother updating if status has changed since we last 
     *  updated, or if we just became the current pane (didSwap) -- 
     *  assuming that status and aDoc are non-nil, of course.
     */

    if ([super updateStatus:aStatus doc:aDoc]
	&& ((status != oldStatus) || didSwap)) {

	BOOL isThreeD, isPolar;
	Window *viewWindow;

	[(viewWindow = [view window]) disableDisplay];

        [threeDButton setState:(isThreeD = [status isThreeD])];
        [threeDButton setEnabled:!(isPolar = [status isPolar])];

        [self _updateRotationIsThreeD:isThreeD];
	[self _updateContourIsThreeD:isThreeD];
	[self _updateSurfaceTypeIsThreeD:isThreeD];
	[self _updateIsoSamplesIsThreeD:isThreeD];

	[viewWindow reenableDisplay];

	[self perform:@selector(selectControl:)
		 with:self
	   afterDelay:1
       cancelPrevious:YES];

	didSwap = NO;
	return YES;
    }

    return NO;
}


- (BOOL)forceUpdateStatus:aStatus doc:aDoc
{
    BOOL	needsRedisplay;

    /*  Update ourselves first, then the options panel  */
    
    needsRedisplay = [super forceUpdateStatus:aStatus doc:aDoc];

    if ([[contourOptionsPanel panel] isVisible])
	[contourOptionsPanel forceUpdate];

    return needsRedisplay;
}



- didSwapIn:sender
{
    [super didSwapIn:self];
    didSwap = YES;
    return self;
}


- doSetThreeD:sender
{
    BOOL isThreeD;

    [status setThreeD:isThreeD = [sender state]];

    /*  
     *  Making changes that might affect other controls in the same 
     *  pane or one of our options panels should update the pane using 
     *  the current status and doc.
     */
    
    if ([self forceUpdateStatus:status doc:doc])
	[view display];

    return self;
}


- doSetSurfaceType:sender
{
    BOOL oldReport = [status report];

    [status setReport:NO];

    switch ([surfaceTypeMatrix selectedTag]) {
    case SURF_WIREFRAME:
	[status setSurface:YES];
	[status setHiddenThreeD:NO];
	break;
    case SURF_OPAQUE:
	[status setSurface:YES];
	[status setHiddenThreeD:YES];
	break;
    case SURF_INVISIBLE:
	[status setSurface:NO];
	[status setHiddenThreeD:NO];
	break;
    }

    [status setReport:oldReport];
    [status reportSettingsChange:self];

    if ([self forceUpdateStatus:status doc:doc])
	[view display];

    return self;
}


- doSetIsoSamples:sender
{
    int samples = [sender intValue];

    if (samples > 1)
	[status setIsoSamplesCoord:[sender selectedTag] to:samples];
    else
	[sender setIntValue:[status isoSamples:[sender selectedTag]]];

    return self;
}


- doSetRotation:sender
{
    if (sender == rotMatrix)
	[status setRotCoord:[sender selectedTag]
			 to:[[sender selectedCell] floatValue]];
    else
	if (sender == rotZSlider)
	    [status setRotCoord:Z_TAG to:359.0 - [sender floatValue]];
	else
	    [status setRotCoord:[sender tag] to:[sender floatValue]];

    [self _updateRotationIsThreeD:[status isThreeD]];
    return self;
}


- doResetRotation:sender
{
    [status resetRotation];
    [self _updateRotationIsThreeD:[status isThreeD]];
    return self;
}


- doSetContourBase:sender
{
    [status setContourBase:[sender state]];
    if ([self forceUpdateStatus:status doc:doc])
	[view display];
    return self;
}


- doSetContourSurface:sender
{
    [status setContourSurface:[sender state]];
    if ([self forceUpdateStatus:status doc:doc])
	[view display];
    return self;
}


- showContourOptionsPanel:sender
{
    if (!contourOptionsPanel)
	contourOptionsPanel = [[ContourOptionsPanel allocFromZone:[self zone]]
			       init];
    [contourOptionsPanel showPanel:self];
    return self;
}



// Shuts up the compiler about unused RCSId
- (const char *) rcsid
{
    return RCSId;
}


@end



@implementation ThreeDPane (Private)

- _updateRotationIsThreeD:(BOOL)isThreeD
{
    float aFloat;
    Box *aBox;
    Cell *aCell;
    BOOL wasEnabled;

    [rotXSlider setFloatValue:aFloat = [status rotCoord:X_TAG]];
    [rotXSlider setEnabled: isThreeD];
    [aCell = [rotMatrix findCellWithTag:X_TAG] setFloatValue:aFloat];
    [aCell setEnabled: isThreeD];

    [rotZSlider setFloatValue:359.0 - (aFloat = [status rotCoord:Z_TAG])];
    [rotZSlider setEnabled: isThreeD];
    [aCell = [rotMatrix findCellWithTag:Z_TAG] setFloatValue:aFloat];
    [aCell setEnabled: isThreeD];

    [rotationResetButton setEnabled:isThreeD];

    /* 
     *  If the plot is not threeD, we'll make the text title of the 
     *  box dark gray to indicate that all 3d rotation is disabled.  
     *  We only redisplay if the enabledment changes.
     */
    wasEnabled = [[aBox = [[rotXSlider superview] superview] cell] isEnabled];
    if (wasEnabled != isThreeD)
        [[aBox cell] setEnabled: isThreeD];

    return self;
}


- _updateContourIsThreeD:(BOOL)isThreeD
{
    BOOL isOpaque = [status hiddenThreeD];
    BOOL contourBase = [status contourBase];
    BOOL contourSurface = [status contourSurface];

    [[[[contourBaseButton superview] superview] cell] setEnabled:isThreeD];

    [contourBaseButton setState:contourBase];
    [contourBaseButton setEnabled:isThreeD];

    /* 
     * Contours on surfaces don't seem to show up when hidden
     * line removal is turned on (in 3.3 beta).
     */
    //
    [contourSurfaceButton setState:contourSurface && !isOpaque];
    [contourSurfaceButton setEnabled:isThreeD && !isOpaque];

    [contourOptionsButton setEnabled:isThreeD && (contourBase ||
					(contourSurface && !isOpaque))];

    return self;
}



- _updateSurfaceTypeIsThreeD:(BOOL)isThreeD
{
    Box *aBox;
    BOOL wasEnabled;

    wasEnabled = [[aBox = [[surfaceTypeMatrix superview] superview]
		   cell] isEnabled];
    if (wasEnabled != isThreeD)
        [[aBox cell] setEnabled: isThreeD];

    if ([status surface]) {
	if ([status hiddenThreeD])
	    [surfaceTypeMatrix selectCellWithTag:SURF_OPAQUE];
	else
	    [surfaceTypeMatrix selectCellWithTag:SURF_WIREFRAME];
    } else
	[surfaceTypeMatrix selectCellWithTag:SURF_INVISIBLE];

    [surfaceTypeMatrix setEnabled:isThreeD];

    return self;
}



- _updateIsoSamplesIsThreeD:(BOOL)isThreeD
{
    BOOL wasEnabled;
    Box *aBox;

    [[isoSamplesMatrix findCellWithTag:X_TAG] setIntValue:
     [status isoSamples:X_TAG]];

    [[isoSamplesMatrix findCellWithTag:Y_TAG] setIntValue:
     [status isoSamples:Y_TAG]];

    [isoSamplesMatrix setEnabled:isThreeD];
    [isoSamplesLabel setTextGray: isThreeD? NX_BLACK: NX_DKGRAY];

    wasEnabled = [[aBox = [[isoSamplesMatrix superview]
					     superview] cell] isEnabled];
    if (wasEnabled != isThreeD)
	[[aBox cell] setEnabled: isThreeD];

    return self;
}



@end
